package org.oschina.api.user.follow.dao;

import java.util.List;

import org.oschina.Constants;
import org.oschina.api.BaseDAO;
import org.oschina.api.user.follow.model.UserFollow;
import org.oschina.api.user.follow.vo.UserFollowVo;
import org.oschina.api.user.user.dao.UserDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class UserFollowDAO extends BaseDAO {

	@Autowired
	private UserDAO userDAO;
	
	private final String findVo_source="SELECT concat(usf.id,'_',usf.source,'_',usf.target) as 'id',us.id as 'source.id',us.username as 'source.username',us.headphoto as 'source.headphoto' FROM "
		+Constants.DB_USER+" us,"+Constants.DB_USER_FOLLOW+" usf WHERE us.id=usf.source";
	
	private final String findVo_target="SELECT concat(usf.id,'_',usf.target,'_',usf.source) as 'id',us.id as 'target.id',us.username as 'target.username',us.headphoto as 'target.headphoto' FROM "
		+Constants.DB_USER+" us,"+Constants.DB_USER_FOLLOW+" usf WHERE us.id=usf.target";
	
	private final String findVoByTarget=findVo_source+" AND usf.target=? ORDER BY usf.create_time DESC LIMIT ?,?";
	/**
	 * 根据目标返回
	 * @param first
	 * @param max
	 * @return
	 */
	public List<UserFollowVo> findVoByTarget(int target,int first,int max)
	{
		if(_isNeedCache(target))
				return getQueryHelper().query_cache(findVoByTarget, new Object[]{target,first,max}, UserFollowVo.class);
		
		return getQueryHelper().query(findVoByTarget, new Object[]{target,first,max}, UserFollowVo.class);
	}
	
	/**
	 * 根据目标返回数量
	 * @param target
	 * @return
	 */
	public int getCountByTarget(int target)
	{
		if(_isNeedCache(target))
			return (int) getQueryHelper().queryDataSum_cache(new String[]{"target=?"}, new Object[]{target}, UserFollowVo.class);
		
		return (int) getQueryHelper().queryDataSum(new String[]{"target=?"}, new Object[]{target}, UserFollowVo.class);
	}
	
	private final String findVoBySource=findVo_target+" AND usf.source=? ORDER BY usf.create_time DESC LIMIT ?,?";
	/**
	 * 根据源返回
	 * @param first
	 * @param max
	 * @return
	 */
	public List<UserFollowVo> findVoBySource(int source,int first,int max)
	{
		if(_isNeedCache(source))
			return getQueryHelper().query_cache(findVoBySource, new Object[]{source,first,max}, UserFollowVo.class);
			
		return getQueryHelper().query(findVoBySource, new Object[]{source,first,max}, UserFollowVo.class);
	}
	/**
	 * 根据源返回数量
	 * @param source
	 * @return
	 */
	public int getCountBySource(int source)
	{
		if(_isNeedCache(source))
			return (int) getQueryHelper().queryDataSum_cache(new String[]{"source=?"}, new Object[]{source}, UserFollowVo.class);
		
		return (int) getQueryHelper().queryDataSum(new String[]{"source=?"}, new Object[]{source}, UserFollowVo.class);
	}
	
	private boolean _isNeedCache(int user)
	{
		return userDAO.isInCache(user) || userDAO.isOnline(user);
	}
	
	/**
	 * 是否关注
	 * @param source
	 * @param target
	 * @return
	 */
	public boolean isFollow(int source,int target)
	{
		//缓存source关注的
		Boolean result=findByCache(source,target);
		if(result==null)
		{
			result=(getQueryHelper().queryForObject(Constants.DB_USER_FOLLOW, new String[]{"id"}, new String[]{"source=?","target=?"}, new Object[]{source,target}, Object.class)!=null);
			putCache(source,target,result);
		}
		
		return result;
	}
	private Boolean findByCache(int source,int target)
	{
		return (Boolean)getCacheHelper().hget(getKey(source), target, Boolean.class);
	}
	private void putCache(int source,int target,boolean value)
	{
		getCacheHelper().hset(getKey(source), target, value, Constants.TIMEOUT_USER_FOLLOW);
	}
	
	private final String _findOnlineIdByTarget="SELECT us.id FROM "+Constants.DB_USER+" us,"+Constants.DB_USER_FOLLOW+" usf WHERE us.id=usf.source AND usf.target=? AND us.online=? LIMIT ?,?";
	/**
	 * 根据目标和在线返回
	 * @param target
	 * @param first
	 * @param max
	 * @return
	 */
	public List<Integer> _findOnlineIdByTarget(int target,int first,int max)
	{
		return getQueryHelper().query(_findOnlineIdByTarget, new Object[]{target,true,first,max}, Integer.class);
	}
	
	private final String _getOnlineByTarget="SELECT COUNT(*) FROM "+Constants.DB_USER+" us,"+Constants.DB_USER_FOLLOW+" usf WHERE us.id=usf.source AND usf.target=? AND us.online=?";
	/**
	 * 根据目标和在线返回数量
	 * @param target
	 * @return
	 */
	public Integer _getOnlineByTarget(int target)
	{
		return (Integer) getQueryHelper().queryForObject(_getOnlineByTarget, new Object[]{target,true}, Integer.class);
	}
	
	/**
	 * 清除关注相关缓存
	 * @param user
	 */
	public void removeCache(int user)
	{
		getCacheHelper().del(getKey(user));
	}
	
	/**
	 * 根据源和目标删除
	 * @param source
	 * @param target
	 * @return
	 */
	public int deleteBySourceAndTarget(int source,int target)
	{
		int reuslt=(int) getQueryHelper().delete(new String[]{"source=?","target=?"}, new Object[]{source,target}, UserFollowVo.class);
		if(reuslt!=0)
			putCache(source,target,false);
		return reuslt;
	}
	
	/**
	 * 创建
	 * @param follow
	 * @return
	 */
	public UserFollow create(UserFollow follow)
	{
		putCache(follow.getSource().getId(),follow.getTarget().getId(),true);
		getQueryHelper().insert(new String[]{"id","source","target","create_time"}, 
				new Object[]{follow.getId(),follow.getSource().getId(),follow.getTarget().getId(),follow.getCreate_time()}, UserFollowVo.class);
		return follow;
	}
	
	private String getKey(int id)
	{
		return Constants.CACHE_USER_FOLLOW+"_"+id;
	}
}
